import type { InputData, Section, View } from '@/common/models/recommend-result';
import { ChartSkinMap } from '@/common/config/echarts-skin';
import { SizeMap } from '@/common/config/briefinfo/card-size';
import { computed, nextTick, ref, type ComputedRef, type Ref } from 'vue';
import AigcDataVisParam from '@/common/config/aigcdatavis'
import { getEventBus } from '@/common/services/chat-event-bus';
import { getCommonds, type ChatCommand } from '@/common/config/chat-command';
import { useAppInfoStore } from '@/stores/app';
import { updateSectionStatus } from './chat-api';
import { ERRORTYPE } from '@/common/config/const';
import type { ChartSelectContent } from '@/common/models/aigc-data-vis';
import type { InsightConfig } from '@/common/models/chat-message';

// 可视化组件需要股票信息
interface Stock {
  // 市场id
  market: string;
  // 股票代码
  code: string;
  // 股票名称
  name: string;
}


// 组件渲染返回值
export interface ComponentRenderReturn {
  // 渲染图表
  renderChart(): void;
  // 切换图表
  changeChart(data: any): void;
  // 数据校验是否成功
  isDataValid(): boolean;
  // 是否支持图表切换
  isSupportChange(): boolean;
  // 销毁图表
  destoryChart(): void;
  // 切换视图索引
  changeViewIndex(index: number): void;
  // 是否自适应高度
  fitHeight: ComputedRef<boolean>;
  // 是否触发自定义事件
  emitCustomEvent: ComputedRef<boolean>;
  // 是否通栏
  fullWidth: ComputedRef<boolean>;
  // 获取当前指令列表
  getCommands: ComputedRef<ChatCommand[]>;
  commondsParam: Ref<ChatCommand[]>
  // 渲染可视化洞察
  renderInsight(insightConfig: InsightConfig): void;
  // 关闭洞察
  closeInsight(): void;
}

// 数据校验
function verifierData(view: View) {
  if (!view) {
    return false;
  }
  // 高定模块暂不处理
  if (view.type === 'fix') {
    return false;
  }
  if (!view.visual) {
    return false;
  }
  if (view.visual && !view.visual.data.length) {
    return false;
  }
  if (view!.visual && !view.visual.output.length) {
    return false;
  }
  return true;
}

function chartClick(clickEvent: { type: string, data: ChartSelectContent }, section: Section, metadata: InputData) {
  console.log('chartClick', clickEvent)
  const { sectionSelectEventBus, updateViewEventBus } = getEventBus()

  if (clickEvent.type === 'view_update') {
    // 时间轴分类点击 卡片高度变化时需进行重新布局 
    nextTick(() => {
      setTimeout(() => {
        updateViewEventBus.emit()
      }, 50)
    })
    return
  }

  const data = clickEvent.data

  const commonds: string[] = ['index_explain']

  const dataKey = data.data[0].key

  const dataType = metadata.attribute_description.filter((item) => item.attribute_name === dataKey)[0]?.attribute_type

  if (data.data.length === 1) {
    if (dataType === 'DOUBLE' && data.selectedType === 'value') {
      commonds.push('index_graphic')
    }
  } else {
    commonds.push('index_graphic')
  }

  sectionSelectEventBus.emit({ section, data, commands: getCommonds(commonds) })
}

/**
 * 格式化参数
 * @param el 挂载元素
 * @param section 模块数据
 * @param skin 主题色
 * @param size 尺寸
 * @param view 渲染视图
 * @param visualIndex 渲染组件索引
 * @param fitHeight 是否自适应高度
 * @param fullWidth 是否通栏
 * @param renderPosition 渲染位置
 * @returns 
 */
function formatParams(el: HTMLElement,
  section: Section,
  skin: string,
  size: string,
  view: View,
  visualIndex: number,
  fitHeight: boolean,
  fullWidth: boolean,
  renderPosition: string,
  insightConfig: InsightConfig | null
) {

  // 组件布局
  const layout = SizeMap[size].layout;

  // 组件信息
  const visual = view.visual;
  const compInfo = view.visual.output[visualIndex];

  // 整合组件信息
  let stocks: Stock[] = [];

  // 组件宽高设置
  const maxHeight = fitHeight ? 536 : 212;
  let width = fullWidth ? 912 : 436;

  // 右侧会话面板宽度设置
  if (renderPosition === 'copilot') {
    width = 309
  }

  // 如果是主副图或K线图，需要传入股票信息
  if (section.kline || compInfo.extension?.kline) {
    stocks = section.stock_meta.map(stock => {
      const { stock_code, stock_name, market_id } = stock;
      return {
        code: stock_code,
        name: stock_name,
        market: market_id
      }
    })
  }

  // 主图设置
  const chartView: { main: any, secondary?: any } = {
    main: {
      layers: [{
        type: compInfo.name,
        encoding: { ...compInfo.parameter },
        maxHeight,
        width,
        ...compInfo.extension,
        stocks,
        customEvent: (data: { type: string, data: ChartSelectContent }) => chartClick(data, section, view.visual.input)
      }]
    }
  };

  // 副图设置
  if (stocks.length > 0 && section.kline) {
    chartView.secondary = {
      layers: [{
        type: 'simpleKline',
        stocks
      }]
    }
  }

  // 新格式
  let params: any = {
    data: [{
      values: JSON.parse(JSON.stringify(visual.data)),
      metadata: view.visual.input
    }],
    view: chartView,
    dom: el,
    layout,
    hook: AigcDataVisParam.hook,
    token: { ...AigcDataVisParam.token, ...ChartSkinMap[skin].config },
  }

  // 旧格式兼容
  if (!fitHeight && !compInfo.extension?.kline) {
    params = {
      legacy: true,
      type: compInfo.name,
      ...compInfo.parameter,
      data: JSON.parse(JSON.stringify(visual.data)),
      dom: el,
      layout,
      hook: AigcDataVisParam.hook,
      token: { ...AigcDataVisParam.token, ...ChartSkinMap[skin].config },
      maxHeight,
      width,
      metadata: view.visual.input,
      style: {
        dvInsight: insightConfig ? insightConfig.config : []
      },
      ...compInfo.extension,
    }
    if (stocks.length > 0) {
      params.stocks = stocks
    }
  }


  return params;
}

/**
 * 卡片组件渲染器
 * @param el 元素dom
 * @param section 模块数据
 * @param skin 当前echart主题
 * @param size 卡片尺寸
 * @param renderPosition 渲染位置 copilot 会话框| page 页面容器
 * @returns ComponentRenderReturn
 */
export function useComponentRender(el: HTMLElement, section: Section, size: string, renderPosition: string): ComponentRenderReturn {

  // 内部设定高度的组件
  const fitHeightComponents = ['timeLine', 'multiTable', 'text']

  // 是否通栏
  const fullWidthComponents = ['multiTable']

  // 有本地事件的组件
  const customEventComponents = ['multiTable', 'timeLine', 'text']

  const localData = ref(section)

  // 修正视图索引
  const viewIndex = computed(() => localData.value.view_index);
  const visualIndex = computed(() => localData.value.visual_index);
  const componentInfo = computed(() => localData.value.view_wrapper && localData.value.view_wrapper.views[viewIndex.value].visual.output[visualIndex.value]);

  // 支持可视化洞察组件
  const supportInsightComponents = ['bar', 'line', 'barLine', 'area'];

  // 视图数据(聚合视图)
  const view = computed(() => localData.value.view_wrapper && localData.value.view_wrapper.views[viewIndex.value]);

  const insightConfig: Ref<InsightConfig | null> = ref(null);

  // 渲染图表
  const renderChart = () => {
    destoryChart();
    if (!isDataValid()) return
    const appStore = useAppInfoStore();
    console.log('skin', appStore.skin)
    const params = formatParams(el, localData.value, appStore.skin, size, view.value, visualIndex.value, fitHeight.value, fullWidth.value, renderPosition, insightConfig.value)
    console.log('param', params);
    try {
      window.AIGCDataVis.render(el, params)
    } catch (error) {
      window.f10log(ERRORTYPE.JS, `组件渲染失败：${error}`, error)
    }
  }

  // 切换视图索引
  const changeViewIndex = (index: number) => {
    console.log('changeViewIndex', index)
    localData.value.view_index = Number(index);
    localData.value.visual_index = 0;
    insightConfig.value = null;
    renderChart();
  }

  // 切换图表
  const changeChart = (data?: any) => {
    destoryChart()
    if (localData.value.visual_index < 0) {
      localData.value.visual_index = 0;
    }
    localData.value.visual_index++;
    if (localData.value.visual_index >= view.value.visual.output.length) {
      localData.value.visual_index = 0;
    }
    setCommands();
    renderChart();
    updateSectionStatus({ ...{ sid: localData.value.id, ext_visual_index: visualIndex.value, ext_view_index: viewIndex.value }, ...data })
  }

  // 数据校验是否成功
  const isDataValid = () => {
    localData.value.view_index = localData.value.view_index === -1 ? 0 : localData.value.view_index;
    localData.value.visual_index = localData.value.visual_index === -1 ? 0 : localData.value.visual_index;
    return verifierData(view.value)
  }

  // 是否支持图表切换
  const isSupportChange = () => {
    if (!isDataValid()) {
      return false;
    }
    return view.value.visual.output.length > 1;
  }

  // 销毁图表
  const destoryChart = () => {
    try {
      window.AIGCDataVis.destroy(el);
    } catch (error) {
      window.f10log(ERRORTYPE.JS, `组件销毁失败：${error}`, error)
    }
  }

  // 是否高度自适应
  const fitHeight = computed(() => {
    if (!isDataValid()) return false
    if (componentInfo.value.extension?.fitHeight !== undefined) return componentInfo.value.extension.fitHeight
    return fitHeightComponents.includes(view.value.visual.output[visualIndex.value].name)
  })

  const fullWidth = computed(() => {
    if (!isDataValid()) return false
    if (componentInfo.value.extension?.fullWidth !== undefined) return componentInfo.value.extension.fullWidth
    return fullWidthComponents.includes(view.value.visual.output[visualIndex.value].name)
  })

  const isSupportInsight = computed(() => {
    if (!isDataValid()) return false
    return supportInsightComponents.includes(view.value.visual.output[visualIndex.value].name)
  })

  // 是否触发自定义事件
  const emitCustomEvent = computed(() => {
    if (!isDataValid()) return false
    return customEventComponents.includes(view.value.visual.output[visualIndex.value].name)
  })


  // 设置指令列表
  const setCommands = function () {
    // 不改变索引情况下清空指令列表
    commondsParam.value.length = 0;
    // 不改变索引情况下设置指令列表
    Object.assign(commondsParam.value, getCommands.value)
  }

  const getCommands = computed(() => {
    const commands = [];

    if (isSupportInsight.value) {
      if (insightConfig.value) {
        commands.push('close_insight')
      } else {
        commands.push('visual_insight')
      }
    }
    if (isDataValid()) {
      commands.push('card_analyze')
    }
    if (isSupportChange()) {
      commands.push('card_change')
    }
    // commands.push('card_edit')
    commands.push('card_delete')

    return getCommonds(commands);
  })

  const commondsParam: Ref<ChatCommand[]> = ref(getCommands.value)

  const renderInsight = function (config: InsightConfig) {
    const formatViewIndex = config.param.view_index === -1 ? 0 : config.param.view_index;
    const formatVisualIndex = config.param.visual_index === -1 ? 0 : config.param.visual_index;
    // 验证是否当前图表
    if ((formatViewIndex !== viewIndex.value) || (formatVisualIndex !== visualIndex.value)) {
      return;
    }
    insightConfig.value = config;
    renderChart()
    setCommands()
  }

  const closeInsight = function () {
    insightConfig.value = null;
    renderChart()
    setCommands()
  }


  return {
    renderChart,
    changeChart,
    isDataValid,
    isSupportChange,
    destoryChart,
    fitHeight,
    emitCustomEvent,
    fullWidth,
    changeViewIndex,
    getCommands,
    commondsParam,
    renderInsight,
    closeInsight
  }
}